package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;


    /**
     * 上传音频文件
     *
     * @param file 音频文件
     * @return 涵盖音频文件的fileId和mediaUrl的map
     */
    @Override
    public Map<String, Object> uploadTrack(MultipartFile file) {
        return vodService.uploadTrack(file);
    }


    /**
     * 保存音频文件到专辑中
     *
     * @param trackInfoVo 音频文件信息vo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {

        TrackInfoServiceImpl proxy = (TrackInfoServiceImpl) AopContext.currentProxy();

        /**
         * 新增音频文件需要对三个表进行操作
         * 1.track_info
         * 2.track_stat
         * 3.album_info --> 表中有一个include_track_count字段，即专辑集数，我们需要让他+1
         */
        //===========track_info=============
        //1.创建出与数据库交互的实体类对象
        TrackInfo trackInfo = new TrackInfo();
        //2.拷贝vo对象属性到实体类当中
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //3.手动为实体类补充属性
        trackInfo.setUserId(AuthContextHolder.getUserId());
        trackInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        //音频信息中的orderNum属性是当前音频在专辑中的排序值，从0开始依次递增，值越小排序越前
        //因此我们要先根据专辑id去专辑中查询根据orderNum值降序排序的第一个声音的orderNum值
        //我们新添加的音频要在该orderNum值的基础上+1
        //若该专辑中还没有声音，那么我们就设置当前音频的orderNum为1
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .eq(TrackInfo::getIsDeleted, 0)
                .orderByDesc(TrackInfo::getOrderNum)
                .last("limit 1");
        TrackInfo latestTrackInfo = trackInfoMapper.selectOne(queryWrapper);
        trackInfo.setOrderNum(null == latestTrackInfo ? 1 : latestTrackInfo.getOrderNum() + 1);
        //4.前端传来的trackInfoVo对象中没有封装mediaUrl属性，只给封装了mediaFileId属性
        //  因此我们需要自己根据已有信息，获取mediaUrl
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaUrlByMediaFileId(trackInfo.getMediaFileId());
        //5.组装trackInfo
        if (trackMediaInfoVo != null) {
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
            trackInfo.setMediaType(trackMediaInfoVo.getType());
        }
        //6.将组装好的实体类存入数据库中
        trackInfoMapper.insert(trackInfo);

        //===========track_stat=============
        //7.初始化音频统计信息表
        proxy.initTrackStat(trackInfo.getId());


        //===========album_info=============
        //8.对album_info表中的include_track_count字段加一
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (albumInfo != null) {
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        }
        albumInfoMapper.updateById(albumInfo);

    }

    /**
     * 分页查询用户名下的音频数据
     *
     * @param trackInfoIPage 分页对象
     * @param query          查询信息对象vo
     * @return 包含了音频数据的分页集合对象
     */
    @Override
    public IPage<TrackListVo> findUserTrackPage(IPage<TrackListVo> trackInfoIPage, TrackInfoQuery query) {
        return trackInfoMapper.findUserTrackPage(trackInfoIPage, query);
    }


    /**
     * 根据id查询音频信息
     *
     * @param trackId 音频id
     * @return 音频信息
     */
    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        return trackInfo;
    }


    /**
     * 修改音频信息
     *
     * @param trackId     音频id
     * @param trackInfoVo 音频修改信息vo
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //1.先获取旧的数据
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        if (null == trackInfo) {
            throw new GuiguException(201, "修改目标不存在");
        }
        //2.将vo中的数据覆盖原先的旧数据
        //但是在覆盖之前先保存一份旧的数据的音频源信息 --> 用于第三步判断是否需要修改音频信息
        String oldFileId = trackInfo.getMediaFileId();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);

        //3.但是vo中对于音频源的修改只传来了mediaFileId，没有mediaUrl，这一部分我们需要手动赋值
        //  我们首先要判断音频源是否被修改，只有被修改的情况下我们才需要进行赋值
        String newFileId = trackInfoVo.getMediaFileId();
        if (!oldFileId.equals(newFileId) && !StringUtils.isEmpty(newFileId)) {
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaUrlByMediaFileId(newFileId);
            if (trackMediaInfoVo != null) {
                trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
                trackInfo.setMediaSize(trackMediaInfoVo.getSize());
                trackInfo.setMediaDuration(BigDecimal.valueOf(trackMediaInfoVo.getDuration()));
                trackInfo.setMediaType(trackMediaInfoVo.getType());
            }
        }
        //4.将旧的音频源从vod服务器上删除
        vodService.removeMedia(oldFileId);
        //5.将实体类存入数据库当中
        trackInfoMapper.updateById(trackInfo);
    }

    /**
     * 删除音频信息
     *
     * @param trackId 音频id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeTrackInfo(Long trackId) {
        /**
         * 删除一个音频信息，我们需要对如下表进行操作：
         * track_info
         * track_stat
         * album_info  -->  删除一个音频，要让album_info当中的include_track_count字段减1
         * =========================================================================
         * 同时，我们还需要对如下细节进行修改
         * 1.对于音频排序的orderNum进行重新排序
         * 2.从VOD服务器中删除对应的音源信息
         */
        TrackInfo trackInfo = this.getById(trackId);
        //1.============album_info==============
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoMapper.selectOne(new LambdaQueryWrapper<AlbumInfo>()
                .eq(AlbumInfo::getId, albumId));
        if (null == albumInfo) {
            throw new GuiguException(201, "当前声音无归属专辑");
        }
        //让集数字段 - 1
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);

        //2.对于音频排序的orderNum进行重新排序
        //2.1 先获取当前这个音频的orderNum
        Integer orderNum = trackInfo.getOrderNum();
        trackInfoMapper.updateOrderNum(albumInfo.getId(), orderNum);

        //3.删除track_info表中的数据
        trackInfoMapper.deleteById(trackId);

        //4.删除track_stat表中的数据
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>()
                .eq(TrackStat::getTrackId, trackId));

        //5.从VOD服务器中删除对应的音源信息
        vodService.removeMedia(trackInfo.getMediaFileId());
    }


    /**
     * 根据专辑id获取当前专辑下的音频信息
     *
     * @param albumId 专辑id
     * @param page    分页数据
     * @return 音频数据
     */
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, IPage<AlbumTrackListVo> page) {
        //1.从数据库查数据，但是我们返回的数据是不包含isShowPaiMark(true/false)的，所以我们需要手动赋值
        IPage<AlbumTrackListVo> trackListFromDB = trackInfoMapper.findAlbumTrackPage(albumId, page);
        //2.我们对不同专辑的价格类型进行操作 /免费/VIP免费/付费
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        String payType = albumInfo.getPayType();
        String priceType = albumInfo.getPriceType();
        Integer tracksForFree = albumInfo.getTracksForFree();
        Long userId = AuthContextHolder.getUserId();

        switch (payType) {
            //2.1 专辑是免费
            case SystemConstant.ALBUM_PAY_TYPE_FREE -> {
            }
            //2.2 专辑是VIP免费
            case SystemConstant.ALBUM_PAY_TYPE_VIPFREE -> {
                trackListFromDB = dealWithVIPTrackInfoList(trackListFromDB, albumId, priceType, userId, tracksForFree);
            }
            //2.3 专辑是付费类型
            case SystemConstant.ALBUM_PAY_TYPE_REQUIRE -> {
                trackListFromDB = dealWithNeedPaidTrackInfoList(trackListFromDB, albumId, priceType, userId, tracksForFree);
            }
        }
        return trackListFromDB;
    }

    /**
     * 根据音频id获取音频的统计信息
     *
     * @param trackId 音频id
     * @return 音频统计信息
     */
    @Override
    public TrackStatVo getTrackStatVo(Long trackId) {
        return trackStatMapper.getTrackStatVo(trackId);
    }


    /**
     * 根据音频id集合获取音频信息
     *
     * @param trackIdList 音频id集合
     * @return 音频信息
     */
    @Override
    public List<TrackListVo> getTrackInfoListByIds(List<Long> trackIdList) {
        List<TrackInfo> trackInfoList = trackInfoMapper.selectBatchIds(trackIdList);

        List<TrackListVo> result = trackInfoList.stream().map(info -> {
            TrackListVo trackListVo = new TrackListVo();
            BeanUtils.copyProperties(info, trackListVo);
            trackListVo.setTrackId(info.getId());
            return trackListVo;
        }).toList();

        if (!CollectionUtils.isEmpty(result)) {
            return result;
        }
        return List.of();
    }


    /**
     * 处理 [VIP免费] 类型的专辑的音频数据
     *
     * @param trackListFromDB 初始音频数据
     * @param albumId         专辑id
     * @param priceType       单集付费/整专辑付费
     * @param userId          用户id
     * @param tracksForFree   专辑免费集数
     * @return 赋值过isShowPaidMark的音频数据
     */
    private IPage<AlbumTrackListVo> dealWithVIPTrackInfoList(IPage<AlbumTrackListVo> trackListFromDB, Long albumId, String priceType, Long userId, Integer tracksForFree) {
        //1.第一步判断用户是否登录
        //1.1 如果用户没有登录，我们就只给他展示免费的集数
        List<AlbumTrackListVo> albumTrackListVoList = trackListFromDB.getRecords();
        if (null == userId) {
            List<AlbumTrackListVo> list = albumTrackListVoList.stream()
                    .filter(track -> track.getOrderNum() <= tracksForFree)
                    .toList();
            return trackListFromDB.setRecords(list);
        }
        //1.2 若用户有登录，那么我们就进一步判断

        //2.我们判断一下用户是否满足身份是vip的条件
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
        UserInfoVo userInfoVo = userInfoVoResult.getData();
        Assert.notNull(userInfoVo, "TrackInfoServiceImpl调用user微服务的getUserInfoVo方法出错");

        Integer isVip = userInfoVo.getIsVip();
        Date vipExpireTime = userInfoVo.getVipExpireTime();

        //2.1 如果当前用户不是VIP用户，那么我们就将除了免费集数外的音频设置为付费的
        if (0 == isVip || 1 == isVip && vipExpireTime.before(new Date())) {
            return dealTrackInfoListByPriceType(trackListFromDB, albumId, priceType, userId, tracksForFree);
        } else {
            //2.2 当前用户是VIP用户，对于VIP免费的专辑音频，全部显示免费给他
            return trackListFromDB;
        }

    }


    /**
     * 处理 [付费] 类型的专辑的音频数据
     *
     * @param trackListFromDB 初始音频数据
     * @param albumId         专辑id
     * @param priceType       单集付费/整专辑付费
     * @param userId          用户id
     * @param tracksForFree   专辑免费集数
     * @return 赋值过isShowPaidMark的音频数据
     */
    private IPage<AlbumTrackListVo> dealWithNeedPaidTrackInfoList(IPage<AlbumTrackListVo> trackListFromDB, Long albumId, String priceType, Long userId, Integer tracksForFree) {
        //如果用户没有登录，我们就只给他展示免费的集数
        List<AlbumTrackListVo> albumTrackListVoList = trackListFromDB.getRecords();
        if (null == userId) {
            List<AlbumTrackListVo> list = albumTrackListVoList.stream()
                    .filter(track -> track.getOrderNum() <= tracksForFree)
                    .toList();
            return trackListFromDB.setRecords(list);
        }

        return dealTrackInfoListByPriceType(trackListFromDB, albumId, priceType, userId, tracksForFree);
    }


    /**
     * 根据priceType是单集付费或是整专辑付费，来对音频数据进行处理
     *
     * @param trackListFromDB 初始音频数据
     * @param albumId         专辑id
     * @param priceType       付费类型  单集付费/整专辑付费
     * @param userId          用户id
     * @param tracksForFree   专辑免费集数
     * @return 处理过isShowPaidMark的音频数据
     */
    private IPage<AlbumTrackListVo> dealTrackInfoListByPriceType(IPage<AlbumTrackListVo> trackListFromDB, Long albumId, String priceType, Long userId, Integer tracksForFree) {
        List<AlbumTrackListVo> albumTrackListVoList = trackListFromDB.getRecords();
        //1.先判断专辑的priceType是单集付费还是整专辑付费
        if (SystemConstant.ALBUM_PRICE_TYPE_ONE.equals(priceType)) {
            //如果专辑的付费类型是单集付费，那么我们就要先去获取用户购买过的音频信息，进行比对
            Result<List<UserPaidTrack>> userPaidTrackListResult = userInfoFeignClient.getUserPaidTrackList(userId, albumId);
            List<UserPaidTrack> userPaidTrackList = userPaidTrackListResult.getData();
            Assert.notNull(userPaidTrackList, "TrackInfoServiceImpl调用user微服务的getUserPaidTrackList方法出错");
            //将List转为Map
            Map<Long, String> userPaidTrackMap = userPaidTrackList.stream().collect(Collectors.toMap(UserPaidTrack::getTrackId, item -> "1"));
            //遍历传来的音频数据集，若Map中对于trackId的值为空，则代表用户没有买过，那么就将isShowPaidMark设置为true
            for (AlbumTrackListVo vo : albumTrackListVoList) {
                if (StringUtils.isEmpty(userPaidTrackMap.get(vo.getTrackId())) && vo.getOrderNum() > tracksForFree) {
                    vo.setIsShowPaidMark(true);
                }
            }
            return trackListFromDB.setRecords(albumTrackListVoList);
        } else {
            //2.专辑的priceType是整专辑付费
            //我们就去数据库查询当前用户购买的专辑信息，若存在，则整个专辑的音频都显示免费，若不存在，则将除了免费集数之外的音频数据设置为付费
            Result<List<UserPaidAlbum>> userPaidAlbumListResult = userInfoFeignClient.getUserPaidAlbumList(userId, albumId);
            List<UserPaidAlbum> userPaidAlbumList = userPaidAlbumListResult.getData();
            Assert.notNull(userPaidAlbumList, "TrackInfoServiceImpl调用user微服务的getUserPaidAlbumList方法出错");
            //将List转为Map
            Map<Long, String> userPaidAlbumMap = userPaidAlbumList.stream().collect(Collectors.toMap(UserPaidAlbum::getAlbumId, item -> "1"));
            String isPaid = userPaidAlbumMap.get(albumId);
            //若为空，则说明没有买过，那么我们就将除了免费集数之外的音频设置为付费
            if (StringUtils.isEmpty(isPaid)) {
                List<AlbumTrackListVo> list = albumTrackListVoList.stream()
                        .map(track -> {
                            if (tracksForFree < track.getOrderNum()) {
                                track.setIsShowPaidMark(true);
                            }
                            return track;
                        }).toList();
                return trackListFromDB.setRecords(list);
            } else {
                //若不为空，那么就都是免费，直接返回
                return trackListFromDB;
            }
        }
    }


    /**
     * 初始化音频统计信息表
     *
     * @param trackId 音频id
     */
    @Transactional(rollbackFor = Exception.class)
    public void initTrackStat(Long trackId) {
        ArrayList<String> list = new ArrayList<>();
        list.add(SystemConstant.TRACK_STAT_PLAY);
        list.add(SystemConstant.TRACK_STAT_COLLECT);
        list.add(SystemConstant.TRACK_STAT_PRAISE);
        list.add(SystemConstant.TRACK_STAT_COMMENT);

        for (String type : list) {
            TrackStat trackStat = new TrackStat();
            trackStat.setStatType(type);
            trackStat.setTrackId(trackId);
            trackStat.setStatNum(0);

            trackStatMapper.insert(trackStat);
        }
    }


    /**
     * 根据用户id及音频id获取当前用户访问这个音频的购买信息页面
     *
     * @param trackId 音频id
     * @param userId  用户id
     * @return 当前用户访问当前音频进行购买操作的页面显示数据
     */
    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
        //1.根据当前的trackId，先获取对于音频id的音频对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        if (null == trackInfo) {
            throw new GuiguException(201, "当前音频数据不存在");
        }

        //2.根据当前获取到的音频对象，我们可以获取到对于的专辑id，再根据专辑id获取专辑对象
        //专辑对象中有我们需要的音频价格等信息
        Long albumId = trackInfo.getAlbumId();

        //3.获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (null == albumInfo) {
            throw new GuiguException(201, "当前音频所归属的专辑数据不存在");
        }

        //4.有了专辑对象，我们可以获取到该专辑的音频定价(单集或整专辑)，以及折扣信息
        BigDecimal price = albumInfo.getPrice();

        //5.根据音频对象，获取该音频的排序顺序
        Integer orderNum = trackInfo.getOrderNum();

        //6.我们尝试去获取所有的排序位于当前音频对象的后续音频数据
        LambdaQueryWrapper<TrackInfo> wrapper4GetAllTrackInfoBehindSomeone = new LambdaQueryWrapper<>();
        wrapper4GetAllTrackInfoBehindSomeone.eq(TrackInfo::getAlbumId, albumId)
                .gt(TrackInfo::getOrderNum, orderNum)
                .orderByAsc(TrackInfo::getOrderNum)
                .last("limit 50");
        List<TrackInfo> trackInfoListBehindSomeone = trackInfoMapper.selectList(wrapper4GetAllTrackInfoBehindSomeone);

        //7.获取当前用户在该专辑下的所有的音频购入数据信息
        Result<List<UserPaidTrack>> userPaidTrackList = userInfoFeignClient.getUserPaidTrackList(userId, albumId);
        List<UserPaidTrack> userPaidTrackListData = userPaidTrackList.getData();
        Assert.notNull(userPaidTrackListData, "[TrackInfoServiceImpl] 调用user微服务的 [getUserPaidTrackList] 方法失败");

        //8.将当前用户在当前专辑下的所有的音频消费对象List列表，转换为Map集合
        Map<Long, UserPaidTrack> userPaidTrackMap = userPaidTrackListData.stream().collect(Collectors.toMap(UserPaidTrack::getTrackId, v -> v));

        //9.我们需要将我们查找出的所有的后续的音频列表进行过筛，将已经消费过的音频从后续音频列表中筛除
        //我们过筛过，获取后续的所有可消费音频的ID List
        List<Long> consumableTrackIdList = trackInfoListBehindSomeone.stream()
                .map(TrackInfo::getId)
                .filter(id -> StringUtils.isEmpty(userPaidTrackMap.get(id)))
                .toList();

        //10.通过所有经过处理后，获得到的音频ID集合，我们可以得知，可购买消费的集数具体大小
        int size = consumableTrackIdList.size();

        //11.我们要返回的是一个List<Map<String,Object>>,其中这个List中的每一个Map就是一个可点击消费选项窗口
        //不论如何，都至少会有一个Map存在，那就是购买当前本集
        List resultList = new ArrayList();

        //购买本集的map
        Map map1 = new HashMap();
        map1.put("name", "本集");      //购买窗口的名字
        map1.put("price", price);     //购买窗口的价格
        map1.put("trackCount", 0);    //当前购买窗口显示的购买集数，这里购买本集不展示,使用0填充
        resultList.add(map1);

        //12.我们接下来需要去根据size，来判断会有多少个购买窗口需要显示，一个购买窗口对应一个map，每个购买窗口对应10集
        int block = (size % 10 == 0) ? (size / 10) : (size / 10) + 1;
        for (int i = 1; i <= block; i++) {
            int count = 10 * i;

            //13.根据具体情况，向List中填充Map数据
            if (count > size) {
                Map map3 = new HashMap();
                map3.put("name", "后" + size + "集");
                map3.put("price", price.multiply(new BigDecimal(size)));
                map3.put("trackCount", size);
                resultList.add(map3);
                break;
            }

            Map map2 = new HashMap();
            map2.put("name", "后" + count + "集");
            map2.put("price", price.multiply(new BigDecimal(count)));
            map2.put("trackCount", count);
            resultList.add(map2);
        }

        //14.返回数据
        return resultList;
    }


    /**
     * [rpc]
     * 获取用户当前可购买的声音列表数据
     *
     * @param userId     用户id
     * @param albumId    专辑id
     * @param trackId    音频id
     * @param trackCount 购买集数
     * @return 可购买音频列表
     */
    @Override
    public Result<List> getCanPaidTrackInfoList(Long userId, Long albumId, Long trackId, Integer trackCount) {

        List<TrackInfo> result = new ArrayList<>();

        //1.先去获取当前用户是否有过在指定专辑下有过消费音频的记录
        Result<List<UserPaidTrack>> userPaidTrackListResult = userInfoFeignClient.getUserPaidTrackList(userId, albumId);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackListResult.getData();
        Assert.notNull(userPaidTrackList,"[TrackInfoServiceImpl]在调用user微服务的[getUserPaidTrackList]方法发生错误");

        //2.将用户购买过的音频对象列表转换为Map
        Map<Long, String> userPaidTrackMap = userPaidTrackList.stream().collect(Collectors.toMap(UserPaidTrack::getTrackId, v -> "1"));

        //3.根据trackCount来获取指定数量的trackInfo
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        if (trackCount == 0){
            result.add(trackInfo);
        } else {
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TrackInfo::getAlbumId,albumId);
            wrapper.gt(TrackInfo::getOrderNum,trackInfo.getOrderNum());
            wrapper.last("limit " + trackCount);
            wrapper.orderByAsc(TrackInfo::getOrderNum);
            result = trackInfoMapper.selectList(wrapper);
        }

        //4.接下来我们去遍历trackInfoList，判断这个可购买音频对象列表中是否存在用户已经购买过的音频
        List<Long> exitList = new ArrayList<>();
        for (TrackInfo info : result) {
            if (!StringUtils.isEmpty(userPaidTrackMap.get(info.getId()))){
                exitList.add(info.getId());
                return Result.build(exitList,400,"购买音频列表中存在已经购买过的音频");
            }
        }

        return Result.ok(result);
    }


}
